//
//  EXQuery.m
//  ORM
//
//  Created by PH on 21.12.09.
//  Copyright 2009-2010 Codesign. All rights reserved.
//

#import "EXQuery.h"

@implementation EXQuery

- (id)initWithBlock:(BOOL(^)(id))_block paramString:(NSString*)paramString queryString:(NSString*)queryString varNamesList:(NSString*)varNamesList, ... {
	if ((self = [super init])) {
		block = [_block copy];
		NSRange range = [paramString rangeOfString: @"*"];
		if (range.location != NSNotFound) {
			className = [[[paramString substringToIndex: range.location] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] retain];
			objectVar = [[[paramString substringFromIndex: range.location + 1] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] retain];
		} else {
			range = [paramString rangeOfString: @" "];
			className = [[[paramString substringToIndex: range.location] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] retain];
			objectVar = [[[paramString substringFromIndex: range.location + 1] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] retain];
		}
		NSSet* objects;
		NSString* predicateQuery = [self predicateQuery: queryString objects: &objects];
		@try {
			predicate = [[NSPredicate predicateWithFormat: predicateQuery] retain];
			NSArray* vars = [varNamesList componentsSeparatedByString: @","];
			va_list(args);
			va_start(args, varNamesList);
			localVars = [[NSMutableDictionary alloc] init];
			for (NSString* var in vars) {
				var = [var stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
				if ([objects containsObject: var]) {
					NSString* arg = va_arg(args, NSString*);
					[localVars setObject: arg forKey: var];
				} else {
					int arg = va_arg(args, int);
					[localVars setObject: [NSNumber numberWithInt: arg] forKey: var];
				}
			}
			va_end(args);
		} @catch (NSException* exception) {
			// cannot parse query, won't be optimized
		}
	}
	return self;
}

- (BOOL(^)(id))block {
	return block;
}

- (NSDictionary*)localVars {
	return localVars;
}

- (NSString*)objectVar {
	return objectVar;
}

- (NSString*)predicateQuery:(NSString*)query objects:(NSSet**)objects {
	NSMutableString* newQuery = [NSMutableString string];
	NSMutableSet* _objects = [NSMutableSet set];
	for (NSUInteger i = 0; i < [query length]; i++) {
		unichar c = [query characterAtIndex: i];
		if (c == '[') {
			NSUInteger start = i + 1;
			while (c != ']') {
				i++;
				c = [query characterAtIndex: i];
			}
			NSString* invoc = [query substringWithRange: NSMakeRange(start, i - start)];
			NSRange range = [invoc rangeOfString: @":"];
			[_objects addObject: [[invoc substringFromIndex: range.location + 1] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]];
			invoc = [invoc stringByReplacingOccurrencesOfString: @"isEqual:" withString: @"=="];
			invoc = [invoc stringByReplacingOccurrencesOfString: @"@\"" withString: @"\""];
			[newQuery appendString: invoc];
		} else [newQuery appendFormat: @"%C", c];
	}
	*objects = _objects;
	return newQuery;
}

- (NSPredicate*)predicate {
	return predicate;
}

- (void)dealloc {
	[className release];
	[objectVar release];
	[predicate release];
	[localVars release];
	[block release];
	[super dealloc];
}

@end
